/*
 *Copyright (c) 2024 Black Sesame Technologies
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
*/

#include "hscg_firmware_statistic.h"
#include "eth2can.h"
#ifdef STATISTICS_PACKET_USE_GMAC_PHC_TIMESTAMP
#include "gmac_time.h"
#endif

#ifdef STATISTICS_PACKET_TIMESTAMP_ENABLE
/* max size: 256k 0x40000 */
struct statistics_packet_timestamp_t *statistics_packet_timestamp =
    (struct statistics_packet_timestamp_t *)STATISTICS_PACKET_TIMESTAMP_SRAM_ADDR;

void statistics_packet_loop_inc(void)
{
    if (statistics->packet_timestamp_loop >= (STATISTICS_PACKET_TIMESTAMP_GRPNUM-1))
        statistics->packet_timestamp_loop = 0;
    else
        statistics->packet_timestamp_loop++;
}

void statistics_packet_timestamps_update(uint32 step_inx)
{
    uint32 step;
    uint32 loop = statistics->packet_timestamp_loop;
#ifdef STATISTICS_PACKET_USE_GMAC_PHC_TIMESTAMP
    struct timespec64 phc_time;
#endif

    if (step_inx >= TIMESTAMP_PACKET_NUM)
        statistics->packet_timestamp_step = 0;
    else
        statistics->packet_timestamp_step = step_inx;

    step = statistics->packet_timestamp_step;
#ifdef STATISTICS_PACKET_USE_GMAC_PHC_TIMESTAMP
    phc_time.tv_sec = ~0;
    phc_time.tv_nsec = ~0;
    gmac_get_phc_time(&phc_time);
    statistics_packet_timestamp[loop].timestamp[step] = ((uint64)phc_time.tv_sec << 32) | (uint64)phc_time.tv_nsec;
#else
    statistics_packet_timestamp[loop].timestamp[step] = util_get_GTC_time64();
#endif
}

void statistics_packet_timestamp_init(void) {
    int i;

    statistics->packet_timestamp_loop = STATISTICS_PACKET_TIMESTAMP_GRPNUM;
    if (sizeof(struct statistics_packet_timestamp_t) > (STATISTICS_PACKET_TIMESTAMP_SRAM_ADDR_END - STATISTICS_PACKET_TIMESTAMP_SRAM_ADDR)) {
        hprintf(DEBUG, "Error: %s: size of struct statistics_packet_timestamp_t is too large!\n", __func__);
        return;
    }

    for (i = 0; i < STATISTICS_PACKET_TIMESTAMP_GRPNUM; i++) {
        memset(&statistics_packet_timestamp[i], 0, sizeof(struct statistics_packet_timestamp_t));
    }
}

void statistics_packet_data_update(uint32 id, uint8 *data, uint32 len)
{
    uint32 data_len = len;

    statistics_packet_timestamp[statistics->packet_timestamp_loop].id = id;
    if (len > STATISTICS_PACKET_DATA_SIZE)
        data_len = STATISTICS_PACKET_DATA_SIZE;
    memcpy(statistics_packet_timestamp[statistics->packet_timestamp_loop].data, data, data_len);
}

#endif /* STATISTICS_PACKET_TIMESTAMP_ENABLE */
